
#ifndef __datashuttle_smart_poniter_header_file_h__
#define __datashuttle_smart_poniter_header_file_h__

#include <stdlib.h>
#include <string>
#include <exception>

namespace datashuttle{

class AtomicInt
{
public:
	AtomicInt() : _v (0) {}
	
	void set( int newValue) { _v = newValue; }
	int get() { return _v; }

	void inc(void);
	void dec(void);
	bool decThenIfZero(void);
	int  add(int v);

protected:
	volatile int _v;
};

inline void AtomicInt::inc(void)
{
	__asm__ __volatile__(
		"lock ; incl %0"
		:"=m" (_v)
		:"m" (_v)
	);
}

inline void AtomicInt::dec(void)
{
	decThenIfZero();
}

inline bool AtomicInt::decThenIfZero(void)
{ 
	unsigned char c;
	__asm__ __volatile__(
		"lock ; decl %0; sete %1"
		:"=m" (_v), "=qm" (c)
		:"m" (_v) : "memory"
	);
	
	return c != 0;
}

inline int AtomicInt::add(int v)
{
	int tmp = _v;

	__asm__ __volatile__(
		"lock; xadd %1,%0"
		:"=m"(_v) 
		:"r"(v)
	);

	return tmp;
}

class SharedObjExpcetion : public std::exception
{
public:
	SharedObjExpcetion(const std::string& what_arg);
	virtual ~SharedObjExpcetion() throw() {}
	const char* what() const throw()
	{
		return mWhat.c_str();
	}
private:
	std::string mWhat;
};

class NullSharedObjException : SharedObjExpcetion
{
public:
	NullSharedObjException(const std::string& what_arg);
};

class SharedObject
{
public:
	SharedObject() ;
	SharedObject(const SharedObject&);

	virtual ~SharedObject();

	SharedObject& operator=(const SharedObject)
	{
		//copy is not permitted
		return *this;
	}
	
	bool operator == ( const SharedObject& b);
	
	void __incRef( );
	void __decRef( );
	int __getRef();
	void __setNoDelete(bool noDel);
	
protected:
	AtomicInt	_ref;
	bool		_noDelete;
};

template<typename T>
class Pointer
{
public:
	typedef T element_type;
	T* _ptr;
	
	Pointer(T* p = NULL)
	{
		this->_ptr = p;

		if (this->_ptr)
			this->_ptr->__incRef();
	}
	
	template<typename Y>
	Pointer(const Pointer<Y>& r)
	{
		this->_ptr = r._ptr;

		if (this->_ptr)
			this->_ptr->__incRef();
	}

	Pointer(const Pointer& r)
	{
		this->_ptr = r._ptr;

		if (this->_ptr)
			this->_ptr->__incRef();
	}
	
	Pointer& operator=(const Pointer& r)
	{
		if(this->_ptr != r._ptr)
		{
			if (r._ptr)
				r._ptr->__incRef();

			T* ptr = this->_ptr;
			this->_ptr = r._ptr;

			if (ptr)
				ptr->__decRef();
		}
		
		return *this;
	}

	template<class Y>
	static Pointer dynamicCast(const Pointer<Y>& r)
	{
		return Pointer(dynamic_cast<T*>(r._ptr));
	}

	template<class Y>
	static Pointer dynamicCast(Y* p)
	{
		return Pointer(dynamic_cast<T*>(p));
	}
	
	T* get() const { return _ptr; }

	inline T* operator->() const
	{
		if (!_ptr)
		{
			throwNullObjectHandleException(__FILE__, __LINE__);           
		}

		return _ptr;
	}

	inline T& operator*() const
	{
		if (!_ptr)
		{
			throwNullObjectHandleException(__FILE__, __LINE__);           
		}

		return *_ptr;
	}

	operator bool() const
	{
		return _ptr ? true : false;
	}

	void swap(Pointer& other)
	{
		std::swap(_ptr, other._ptr);
	}

protected:

	void throwNullObjectHandleException(const char *, int) const;
};

template<typename T>
inline void Pointer<T>::throwNullObjectHandleException(const char* file, int line) const
{
	throw NullSharedObjException("Null ObjectHandle");
}

template<typename T, typename U>
inline bool operator ==(const Pointer<T>& lhs, const Pointer<U>& rhs)
{
	T* l = lhs.get();
	U* r = rhs.get();
	if(l && r)
		return *l == *r;

	return !l && !r;
}

template<typename T, typename U>
inline bool operator!=(const Pointer<T>& lhs, const Pointer<U>& rhs)
{
	T* l = lhs.get();
	U* r = rhs.get();
	if(l && r)
		return *l != *r;

	return l || r;
}

template<typename T, typename U>
inline bool operator<(const Pointer<T>& lhs, const Pointer<U>& rhs)
{
	T* l = lhs.get();
	U* r = rhs.get();
	if(l && r)
		return l < r;

	return !l && r;
}

}//namespace datashuttle

#endif // __datashuttle_smart_poniter_header_file_h__


